package com.wkck.service.impl;

import cn.hutool.core.lang.Tuple;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.wkck.VO.UserAllInfoVo;
import com.wkck.VO.UserDeliveredCareersVo;
import com.wkck.constant.JwtClaimsConstant;
import com.wkck.domain.DeliveredLibraryHistory;
import com.wkck.domain.LResume;
import com.wkck.domain.User;
import com.wkck.domain.UserElseInfo;
import com.wkck.dto.QueryUserConditionDto;
import com.wkck.dto.UserLoginDto;
import com.wkck.exception.BaseException;
import com.wkck.exception.FileNotFoundException;
import com.wkck.exception.UploadErrorException;
import com.wkck.mapper.*;
import com.wkck.properties.JwtProperties;
import com.wkck.service.UserFrontendService;
import com.wkck.service.UserService;
import com.wkck.utils.JwtUtil;
import io.minio.MinioClient;
import io.minio.RemoveObjectArgs;
import io.minio.UploadObjectArgs;
import lombok.extern.slf4j.Slf4j;
import org.apache.logging.log4j.util.Strings;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;
import org.springframework.util.StringUtils;

import javax.servlet.http.HttpSession;
import java.io.File;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * @Author: CK
 * @Date: 2024/02/28/18:11
 * @Description:
 */
@Service
@Slf4j
public class UserFrontendServiceImpl implements UserFrontendService {

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private UserElseInfoMapper userElseInfoMapper;

    @Autowired
    private LResumeMapper resumeMapper;

    @Autowired
    private LResumeFilesMapper filesMapper;

    @Autowired
    private DeliveredLibraryMapper deliverMapper;

    @Autowired
    private DeliveredLibraryHistoryMapper historyMapper;

    @Autowired
    private JwtProperties jwtProperties;

    @Autowired
    private MinioClient minioClient;

    private static final String bucket = "avatars";

    @Override
    public Map<String, Object> login(UserLoginDto userLoginDto, HttpSession session) {

        if (Objects.isNull(userLoginDto)) {
            throw new BaseException("登录信息为空！");
        }

        if (!StringUtils.hasLength(userLoginDto.getUsername()) || !StringUtils.hasLength(userLoginDto.getPassword())) {
            throw new BaseException("账号或密码不能为空！");
        }

        if (!StringUtils.hasLength(userLoginDto.getCode())) {
            throw new BaseException("验证码不能为空！");
        }

        String kaptchaCode = session.getAttribute("verifyCode")+"";
        if (!StringUtils.hasLength(kaptchaCode)|| !userLoginDto.getCode().toLowerCase().equals(kaptchaCode)){
            throw new BaseException("验证码错误！");
        }

        User user = userMapper.getUserMsgByUserName(userLoginDto.getUsername());

        Map<String, Object> responseVo = new HashMap<>();

        if (Objects.isNull(user)) {
            // 可以注册并登录
            User userEmpty = new User();
            BeanUtils.copyProperties(userLoginDto, userEmpty);
            userEmpty.setUser_image("avatars/default.jpg");
            userEmpty.setCreate_time(LocalDateTime.now());
            userEmpty.setPassword(DigestUtils.md5DigestAsHex(userLoginDto.getPassword().getBytes(StandardCharsets.UTF_8)));

            userMapper.insert(userEmpty);

            user = userMapper.getUserMsgByUserName(userLoginDto.getUsername());

            // 直接登录
            returnVo(userLoginDto, user, responseVo);
        } else {
            if (!user.getPassword().equals(DigestUtils.md5DigestAsHex(userLoginDto.getPassword().getBytes(StandardCharsets.UTF_8)))) {
                throw new BaseException("密码错误！");
            }
            // 直接登录
            returnVo(userLoginDto, user, responseVo);
        }

        return responseVo;
    }

    @Override
    public UserAllInfoVo getUserAllInfoById(Integer id) {
        return userMapper.getUserAllInfoById(id);
    }

    @Override
    public Boolean modifyUserBaseInfo(Integer id, User user) {

        if (user.getPassword() != null && !user.getPassword().equals("")) {
            user.setPassword(DigestUtils.md5DigestAsHex(user.getPassword().getBytes(StandardCharsets.UTF_8)));
        }

        userMapper.updateUserBaseInfo(id, user);

        return true;
    }

    @Override
    public Boolean modifyUserElseInfo(Integer id, UserElseInfo userElseInfo) {
        LambdaQueryWrapper<UserElseInfo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UserElseInfo::getUser_id, id);
        UserElseInfo elseInfo = userElseInfoMapper.selectOne(queryWrapper);

        if (Objects.isNull(elseInfo)) {
            userElseInfo.setUser_id(id);
            userElseInfoMapper.insert(userElseInfo);
        } else {
            LambdaUpdateWrapper<UserElseInfo> updateWrapper = new LambdaUpdateWrapper<>();
            updateWrapper.eq(UserElseInfo::getUser_id, id);
            userElseInfoMapper.update(userElseInfo, updateWrapper);
        }

        return true;
    }

    /***
     * @Author: CK
     * @Date: 2024/3/19
     * @Param: [id]
     * @Description: 根据用户id查询用户已投递的职位
     */
    @Override
    public List<UserDeliveredCareersVo> queryUserDeliveredCareersByUserId(Integer id) {

        if (id == null) {
            throw new BaseException("用户信息为空 不允许操作");
        }

        List<UserDeliveredCareersVo> base = userMapper.queryUserDeliveredCareersByUserId(id);

        base.forEach(item -> {
            if (item.getResume_type().equals("online")) {
                item.setResume(resumeMapper.selectById(item.getResume_id()));
            }  else if (item.getResume_type().equals("file")) {
                item.setFile(filesMapper.selectById(item.getResume_id()));
            }
        });

        return base;
    }

    /***
     * @Author: CK
     * @Date: 2024/3/19
     * @Param: [dl_id]
     * @Description: 根据投递id获取投递历史记录
     */
    @Override
    public List<DeliveredLibraryHistory> getDeliverHistoryById(Long dlId) {
        if (dlId == null) {
            throw new BaseException("编号为空 无对应信息!");
        }

        LambdaQueryWrapper<DeliveredLibraryHistory> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper
                .eq(DeliveredLibraryHistory::getDl_id, dlId)
                .orderByDesc(DeliveredLibraryHistory::getCreate_time);

        return historyMapper.selectList(queryWrapper);
    }

    /***
     * @Author: CK
     * @Date: 2024/3/19
     * @Param: [dl_id]
     * @Description: 撤回投递记录
     */
    @Override
    public Boolean withdrawDeliverHistory(Long dlId) {
        if (dlId == null) {
            throw new BaseException("编号为空 无对应信息!");
        }
        deliverMapper.deleteById(dlId);
        log.info("投递记录删除成功！ ===> {}", dlId);

        LambdaQueryWrapper<DeliveredLibraryHistory> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper
                .eq(DeliveredLibraryHistory::getDl_id, dlId);
        historyMapper.delete(queryWrapper);
        log.info("投递历史记录已清空！ ===> {}", dlId);

        return true;
    }

    /***
     * @Author: CK
     * @Date: 2024/3/20
     * @Param: [file]
     * @Description: 修改用户头像
     */
    @Override
    public Boolean changeUserAvatarById(int id, String localFilePath, String filename) {
        File file = new File(localFilePath);

        if (!file.exists()) {
            throw new FileNotFoundException("文件未找到，上传失败!");
        }

        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper
                .eq(User::getId, id);
        User user = userMapper.selectOne(queryWrapper);
        if (Objects.isNull(user)) {
            throw new BaseException("用户信息为空 不允许操作!");
        }

        String real = user.getUser_image().replaceFirst(bucket + "/", "");

        try {
            minioClient.removeObject(
                    RemoveObjectArgs.builder()
                            .bucket(bucket)
                            .object(real)
                            .build()
            );
        } catch (Exception e) {
            throw new BaseException("minio文件删除失败");
        }

        String location = id + "/" + filename;

        try {
            minioClient.uploadObject(
                    UploadObjectArgs.builder()
                            .bucket(bucket)
                            .object("users/" + location)
                            .filename(localFilePath)
                            .build());
            log.info("头像上传成功, {}", location);
        } catch (Exception e) {
            throw new UploadErrorException("头像上传失败");
        }

        LambdaUpdateWrapper<User> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper
                .set(User::getUser_image, bucket + "/users/" + location)
                .eq(User::getId, id);
        userMapper.update(user, updateWrapper);

        log.info("数据库写入结束");

        return true;
    }

    private void returnVo(UserLoginDto userLoginDto, User user, Map<String, Object> responseVo) {
        Map<String, Object> claims = new HashMap<>();
        claims.put(JwtClaimsConstant.USER_ID, user.getId());
        String token = JwtUtil.createJWT(
                jwtProperties.getUserSecretKey(),
                jwtProperties.getUserTtl(),
                claims);

        responseVo.put("token", token);
        responseVo.put("user", user);
    }
}
